#!/cygdrive/c/Python24/python.exe

from gui.poset_p2p import *
import sys
import wx
import os
import poset
import shutil
import gui.dialog
import inspect
import posnet_tcp_client
import request
#-------------------------------------------
# Handlers (functions called by gui action)
# POSET
#--------------
def handle_load_poset(self,event):
	gui.dialog.Load(self,event,self.Poset,"Poset","poset")
	handle_validate_poset(self)
		
def handle_save_poset(self,event):
	gui.dialog.Save(self,event,self.Poset,"Poset","poset")

def handle_validate_poset(self,event = None):
	try:
		set_status(self,"build Poset")
		Poset = poset.build_poset(self.Poset.GetValue())
		set_status(self,"Poset builded")
		self.Poset.Poset =  Poset
	except Exception,e:
		gui.dialog.show_error(self,'while trying to validate poset\n'+str(e))
		
def handle_guess_poset_from_resources(self,event):
	tup = self.get_host_port()
	if tup is not None:
		set_status(self,"get poset : ping "+str(tup))
		self.ping(tup[0],tup[1])
		set_status(self,"get poset : ok")
	else:
		set_status(self,"get poset : failed")

#-------------------------------------------
# Handlers (functions called by gui action)
# Resources 
#--------------
def handle_load_resources(self,event):
	gui.dialog.Load(self,event,self.Resources,"Resources","resources")
	handle_validate_resources(self)

def handle_save_resources(self,event):
	gui.dialog.Save(self,event,self.Resources,"Resources","resources")


def handle_random_resources(self,event):
	num_nodes = self.resources_generator.GetValue()	
	handle_validate_poset(self)
	Resources = poset.random_populate(self.Poset.Poset,num_nodes)
	self.Resources.SetValue( poset.resources_to_str( self.Poset.Poset,Resources) )
	handle_validate_resources(self)

def handle_validate_resources(self,event = None):
	try:
		set_status(self,"read Resources")
		Resources = poset.build_resources(self.Poset.Poset,self.Resources.GetValue())
		self.Resources.Resources =  Resources 
		# build graph
		#set_status(self,"build graph")
		#self.Graph,self.Graph_top_nodes,self.Graph_equal_nodes,self.Graph_duplicate_nodes = graph.buildv2(self.Poset.Poset,self.Resources.Resources,{ "verbose":True })	
		# build data for nodes
		#self.node_data = simulation.build_data(self.Poset.Poset,self.Resources.Resources,self.Graph,self.Graph_top_nodes)
		set_status(self,"Resources ok")
	except Exception,e:
		gui.dialog.show_error(self,'while trying to validate resource\n'+str(e))


#-------------------------------------------
# Handlers (functions called by gui action)
# Requests
#--------------
def handle_load_requests(self,event):
	gui.dialog.Load(self,event,self.Requests,"Requests","requests")
	handle_validate_requests(self)

def handle_save_requests(self,event):
	gui.dialog.Save(self,event,self.Requests,"Requests","requests")

def handle_validate_requests(self,event = None):
	try:
		set_status(self,"build Requests")
		Requests = request.build_requests(self.Poset.Poset,self.Requests.GetValue())
		set_status(self,"Requests builded")
		#Graph
		#set_status(self,"build entry points")
		#Requests = request.build_entry_points(self.Poset.Poset,self.Graph,self.Resources.Resources,Requests)
		#set_status(self,"entry points builded")
		self.Requests.Requests =  Requests 
	except Exception,e:
		gui.dialog.show_error(self,'while trying to validate request\n'+str(e))
		#from traceback import print_exc
		#print_exc()

def handle_random_requests(self,event = None):
	set_status(self,"build Requests")
	Requests = request.random_request(self.Poset.Poset)
	set_status(self,"Requests builded")
	#set_status(self,"build entry points")
	#Requests = request.build_entry_points(self.Poset.Poset,self.Graph,self.Resources.Resources,Requests)
	#set_status(self,"entry points builded")
	self.Requests.SetValue(  request.requests_to_str(self.Poset.Poset,Requests,self.Resources.Resources) )
	handle_validate_requests(self)

#-------------------------------------------
# Handlers (functions called by gui action)
# Graph drawings
#--------------
import Image
import ImageChops
def autocrop(im, bgcolor):
	if im.mode != "RGB":
		im = im.convert("RGB")
	bg = Image.new("RGB", im.size, bgcolor)
	diff = ImageChops.difference(im, bg)
	bbox = diff.getbbox()
	if bbox:
		return im.crop(bbox)
	return None # no contents


def make_image(orig_path,graphic_path):
	if os.path.exists(orig_path):
		im1 = Image.open(orig_path)		
		x,y = im1.size
		width = 600
		height = 600
		if x > y:
			height = int( float(y) * 600.0/float(x) ) 
		else:
			width = int( float(x) * 600.0/float(y) ) 
		try: im1 = autocrop(im1,"white")	
		except: pass	
		im5 = im1.resize((width, height) , Image.BICUBIC) 	
		im5.save( graphic_path)
		print >>sys.stderr,"IMAGE:",graphic_path
	else: 
		if os.path.exists(graphic_path):
			os.remove(graphic_path)
	

def ping(self,host,port):
	Poset = posnet_tcp_client.posnet_ping((host,port))
	self.Poset.SetValue(poset.write_poset(Poset))
	self.handle_validate_poset()	
	return Poset

def handle_ping(self,event = None):
	tup = self.get_host_port()
	if tup is not None:
		host = tup[0]
		port = tup[1]
		# ping
		Poset= self.ping(host,port)
	
		
def get_host_port(self):
	try:
		host = self.text_host.GetValue()
		port = int(self.text_port.GetValue())
		return (host,port)
	except Exception,e:
		gui.dialog.show_error(self,'while trying to get host or port\n'+str(e))

def handle_select_node(self,event = None):
	node  = self.combo_box_overlay_topology.GetValue()
	sp = str(node).split(":")
	if len(sp) > 1:
		self.text_host.SetValue(sp[0])
		self.text_port.SetValue(sp[1])
def handle_insert_random_point(self,event = None):
	tup = self.get_host_port()
	if tup is not None:
		host = tup[0]
		port = tup[1]
	if len(host) >0 and port > 0:
		# ping
		Poset = self.ping(host,port)
		keys = Poset.keys()
		for k  in  keys:
			Poset[k] = range(1,10)
			posnet_tcp_client.posnet_add_random_handle( (host,port), Poset )
		


def handle_draw_node(self,event = None):
	set_status(self,"draw overlay")
	outdir =  os.path.join(os.path.split(sys.argv[0])[0],"tmpdraw")
	outname = "singlenode"
	host =''
	port = 0
	tup = self.get_host_port()
	if tup is not None:
		host = tup[0]
		port = tup[1]
	if len(host) >0 and port > 0:
		# ping
		Poset= self.ping(host,port)
		orig_path = posnet_tcp_client.posnet_draw_node((host,port),outdir,outname,Poset)
		ipath = os.path.join( outdir,"resized_node_graph.png")
		#orig_path  = os.path.join( os.path.split(sys.argv[0])[0], outdir,name)
		make_image(orig_path,ipath)
		if not os.path.exists(ipath):
			self.bitmap_4.SetBitmap(wxBitmap(orig_path, wxBITMAP_TYPE_ANY))
		else:
			self.bitmap_4.SetBitmap(wxBitmap(ipath, wxBITMAP_TYPE_ANY))
		
def handle_draw_overlay(self,event = None):
	self.bitmap_1.SetBitmap(wxBitmap("images/blank.png", wxBITMAP_TYPE_ANY))
	sys.stdout.flush()
	set_status(self,"draw overlay")
	outdir = os.path.join( os.path.split(sys.argv[0])[0],"tmpdraw")
	outname = ""
	host =''
	port = 0
	tup = self.get_host_port()
	if tup is not None:
		host = tup[0]
		port = tup[1]
	if len(host) >0 and port > 0:
		# ping
		Poset= self.ping(host,port)
		# draw		
		overlay_topology = posnet_tcp_client.posnet_draw_topology((host,port),outdir,outname,Poset,self.algo.GetValue())
		self.combo_box_overlay_topology.Clear()
		for overlay_node in overlay_topology:
			hostt = str(overlay_node[0])
			portt = str(overlay_node[1])
			self.combo_box_overlay_topology.Append( hostt+":"+str(portt))
		self.combo_box_overlay_topology.SetStringSelection( host+":"+str(port) )
		#graph.draw_overlay(self.Graph,self.Resources.Resources,self.Graph_top_nodes,self.Graph_duplicate_nodes,self.algo.GetValue(),self.font_size.GetValue(),self.node_size.GetValue())
		graph_path = os.path.join(outdir,"resized_overlay.png")
		orig_path  = os.path.join(outdir,"overlay.png")
		make_image(orig_path,graph_path)
		sgraphic_path = os.path.join( outdir,"resized_semantic_graph.png")
		orig_path  = os.path.join(  outdir,"semantic_graph.png")
		make_image(orig_path,sgraphic_path)
		overl_path = os.path.join( outdir,"resized_semantic_graph_algo"+str(self.algo.GetValue())+".png")
		orig_path  = os.path.join(  outdir,"semantic_graph_algo"+str(self.algo.GetValue())+".png")
		make_image(orig_path,overl_path)
		#shutil.copy(  ,graphic_path)
		self.bitmap_1.SetBitmap(wxBitmap(sgraphic_path, wxBITMAP_TYPE_ANY))
		self.bitmap_2.SetBitmap(wxBitmap(overl_path, wxBITMAP_TYPE_ANY))
		self.bitmap_3.SetBitmap(wxBitmap(graph_path, wxBITMAP_TYPE_ANY))
		set_status(self,"overlay drawn")
		self.Resources.filename="points.tsv"
		self.Resources.dirname=outdir+"/"
		fff=open(os.path.join(self.Resources.dirname,self.Resources.filename),'r')
		data = fff.read().replace("\t",",") 
		self.Resources.SetValue(data)
		fff.close()
		set_status(self,"draw overlay: ok")
	else:
		set_status(self,"draw overlay : error with host or port")


def handle_save_posnet(self,event):
	gui.dialog.SaveFile(self,event,os.path.join(os.path.split(sys.argv[0])[0],"semantic_graph_algo5.png"),"save graph","png")

def handle_save_semantic_graph(self,event):
	gui.dialog.SaveFile(self,event,os.path.join(os.path.split(sys.argv[0])[0],"semantic_graph.png"),"save graph","png")

def handle_save_overlay(self,event):
	gui.dialog.SaveFile(self,event,os.path.join(os.path.split(sys.argv[0])[0],"overlay.png"),"save graph","png")


#-------------------------------------------
# Handlers (functions called by gui action)
# Simulation of requests
#--------------
def handle_save_request(self,event):
	imagenum  = self.saved_request.GetValue()
	imagepath = "example."+str(imagenum)+".png"
	if imagenum == 0 or not os.path.exists(imagepath):
		gui.dialog.show_error("image not found, select one please")
	else:
		gui.dialog.SaveFile(self,event,imagepath,"save request","png")



def handle_execute_request(self,event = None):
	self.bitmap_1.SetBitmap(wxBitmap("blank.png", wxBITMAP_TYPE_ANY))
	sys.stdout.flush()
	self.result_tree.DeleteAllItems()	
	Root = self.result_tree.AddRoot(self.request_type.GetValue()+" results")
	example_num = 0
	self.saved_request.SetRange(1,len(self.Requests.Requests))
	self.saved_request.SetValue(1)
	# boulce pour chaque request
	for Request in self.Requests.Requests:
                noeud_entree = Request[1]
		#------------------------------------
		# simulation
		set_status(self,"simulate propagation")
		algorithme_selectionne = self.request_type.GetValue()
		#------------------------------------
		# recupere l'algorithme
		simulation_function_call  =  simulation.algorithms[algorithme_selectionne]
		nb_arguments = len(inspect.getargspec(simulation_function_call)[0])
		simulation_data = None
		if nb_arguments == 4: # range query :)
			if len(Request[0]) == 1: # on a un request point P que l'on transforme en request range trivial (P,P)
				simulation_data = simulation_function_call(  self.node_data, Request[0][0],Request[0][0], noeud_entree) 
			else:	# on a un request range avec un algo range, RAS
				simulation_data = simulation_function_call(  self.node_data, Request[0][0],Request[0][1], noeud_entree) 
		else: # point query (si c'est un request range, on ne prend en compte que la borne min comme point query)
			simulation_data = simulation_function_call(  self.node_data, Request[0][0], noeud_entree) 
		set_status(self,"end of simulation")
		#------------------------------------
		# get simulation result 
		fit,propag,propag_edges = simulation_data
		nb_visited = dict()
		for node in propag:
			if nb_visited.has_key(node): nb_visited[node] += 1
			else: nb_visited[node] = 1
		#------------------------------------
		# draw request tree
		set_status(self,"draw request tree")
		def get_description(the_node):
			description_string =  poset.resource_to_str(self.Poset.Poset,self.Resources.Resources[the_node]) + " (hits="+str(nb_visited[the_node])+")"
			if the_node in fit: return "*"+description_string
			else: return description_string	
		root = self.result_tree.AppendItem(Root,"[Request "+str(example_num+1)+"] "+ " < ".join( [ poset.resource_to_str(self.Poset.Poset,part) for part in Request[0] ] )+" on "+get_description(propag[0]))
		node_queue  = [ (propag[0],root) ]
		for edge in propag_edges:
			src,dst = edge
			while src !=  node_queue[0][0]:
				del node_queue[0]
			tree_item = node_queue[0][1]
			tree_item_dst = self.result_tree.AppendItem(tree_item, get_description(dst))
			node_queue.append( (dst,tree_item_dst) ) 
		set_status(self,"request tree drawn")
		#------------------------------------
		# draw request
		set_status(self,"draw request")
		graph.draw_request(self.Graph,self.Resources.Resources,self.Graph_top_nodes,self.Graph_duplicate_nodes,self.algo.GetValue(),propag ,propag_edges,Request[0], fit , self.font_size.GetValue(),self.node_size.GetValue())
		graphic_path = os.path.join( os.path.split(sys.argv[0])[0],"reqsuest."+str(example_num+1)+".png")
		orig_path  = os.path.join( os.path.split(sys.argv[0])[0], "example.png")
		make_image(orig_path,graphic_path)
		#shutil.copy("example.png",graphic_path)
		setattr(root,"imagepath",graphic_path)
		self.bitmap_1.SetBitmap(wxBitmap(graphic_path, wxBITMAP_TYPE_ANY))
		set_status(self,"request drawn")
		example_num += 1

def handle_tree_item(self,event):
	item = event.GetItem()
	text = self.result_tree.GetItemText(item)
	if text.startswith("Request "):
		imagepath = "example."+str(text.split(" ")[1])+".png"
		self.bitmap_1.SetBitmap(wxBitmap(imagepath, wxBITMAP_TYPE_ANY))


#------------------------------------------------------------------------------------
class gui_poset_p2p(wxApp):
    def OnInit(self):
        # initialization ############################
        wxInitAllImageHandlers()
	#------------------------------------------------------------
	# set handlers
	setattr(MainFrame,"handle_load_poset",handle_load_poset)
	setattr(MainFrame,"handle_load_resources",handle_load_resources)
	setattr(MainFrame,"handle_load_requests",handle_load_requests)
	setattr(MainFrame,"handle_save_poset",handle_save_poset)
	setattr(MainFrame,"handle_save_resources",handle_save_resources)
	setattr(MainFrame,"handle_save_requests",handle_save_requests)
	setattr(MainFrame,"handle_random_resources",handle_random_resources)
	setattr(MainFrame,"handle_random_requests",handle_random_requests)
	setattr(MainFrame,"handle_validate_poset",handle_validate_poset)
	setattr(MainFrame,"handle_validate_resources",handle_validate_resources)
	setattr(MainFrame,"handle_validate_requests",handle_validate_requests)
	setattr(MainFrame,"handle_guess_poset_from_resources",handle_guess_poset_from_resources)
	setattr(MainFrame,"handle_draw_overlay",handle_draw_overlay)
	setattr(MainFrame,"handle_execute_request",handle_execute_request)
	setattr(MainFrame,"handle_tree_item",handle_tree_item)
	setattr(MainFrame,"handle_save_posnet",handle_save_posnet)
	setattr(MainFrame,"handle_save_overlay",handle_save_overlay)
	setattr(MainFrame,"handle_save_semantic_graph",handle_save_semantic_graph)
	setattr(MainFrame,"handle_save_request",handle_save_request)
	setattr(MainFrame,"handle_ping",handle_ping)
	setattr(MainFrame,"handle_select_node",handle_select_node)
	setattr(MainFrame,"handle_draw_node",handle_draw_node)
	setattr(MainFrame,"ping",ping)
	setattr(MainFrame,"get_host_port",get_host_port)
	setattr(MainFrame,"handle_insert_random_point",handle_insert_random_point)
	#----------------------------------------------------------------
	# instanciate gui frame object
	Gui_frame = MainFrame(None,wx.ID_ANY,"PosNET client")
	#-----------------------------	
	# parametrize algo
	#for algo_name in simulation.algorithms.keys():
	#	Gui_frame.request_type.Append(algo_name)
	#Gui_frame.request_type.SetStringSelection(simulation.algorithms.keys()[-1])
	self.SetTopWindow(Gui_frame)
	#-------------------------------
	# set attributes to the gui frame
	names =  {  "Poset" : dict(),"Resources":[],"Requests":[]}
	for name,def_val in names.items():
		obj = getattr(  Gui_frame  ,name)
		for y in ("filename","dirname"):
			setattr(obj,y,"")
		setattr(obj,name,def_val)
	#for attr in ("Graph","Graph_top_nodes","Graph_equal_nodes","Graph_duplicate_nodes","node_data"):
	#	setattr(Gui_frame,attr,None)
	#-------------------------------
	Gui_frame.Show()
	return 1

def set_status(self,status): self.PosetP2P_statusbar.SetStatusText(status)	
#---------------------------------------------------------------

#-----------------------------------------------
# main entry point of the program	
#-----------------------------------------------
if __name__ == "__main__":
    ### Main ###
    poset_p2p = gui_poset_p2p(0)
    poset_p2p.MainLoop()

